#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
抖音直播间Selenium无头浏览器监听器
基于Selenium WebDriver实现实时评论采集
"""

import logging
import os
import threading
import time
from datetime import datetime
from typing import Callable, Dict, List, Optional

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.common.exceptions import (NoSuchElementException,
                                        TimeoutException, WebDriverException)
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager

logger = logging.getLogger(__name__)


class SeleniumLiveMonitor:
    """基于Selenium的抖音直播间监听器"""

    def __init__(self, room_url: str):
        """
        初始化监听器

        Args:
            room_url: 直播间URL
        """
        self.room_url = room_url
        self.driver = None
        self.is_running = False
        self.callbacks = {"comment": [], "gift": [], "like": [], "enter": []}
        self.processed_comments = set()  # 记录已处理的评论，避免重复
        self.monitor_thread = None

        # 评论区域的可能选择器（需要根据实际页面调整）
        self.comment_selectors = [
            '[data-e2e="comment-list"]',  # 常见的评论列表选择器
            ".comment-list",
            ".live-comment-list",
            ".danmu-list",
            '[class*="comment"]',
            '[class*="danmu"]',
            '[class*="chat"]',
        ]

    def _setup_driver(self):
        """设置Chrome驱动"""
        try:
            chrome_options = Options()

            # 无头模式配置
            chrome_options.add_argument("--headless")
            chrome_options.add_argument("--no-sandbox")
            chrome_options.add_argument("--disable-dev-shm-usage")
            chrome_options.add_argument("--disable-gpu")
            chrome_options.add_argument("--disable-web-security")
            chrome_options.add_argument("--disable-features=VizDisplayCompositor")

            # 模拟真实浏览器
            chrome_options.add_argument(
                "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            )
            chrome_options.add_argument("--window-size=1920,1080")

            # 禁用图片和CSS加载以提高速度
            prefs = {
                "profile.managed_default_content_settings.images": 2,
                "profile.default_content_setting_values.notifications": 2,
                "profile.managed_default_content_settings.stylesheets": 2,
            }
            chrome_options.add_experimental_option("prefs", prefs)

            # 禁用日志
            chrome_options.add_argument("--log-level=3")
            chrome_options.add_experimental_option(
                "excludeSwitches", ["enable-logging"]
            )
            chrome_options.add_experimental_option("useAutomationExtension", False)

            # 手动设置ChromeDriver路径
            chrome_options.binary_location = "/usr/bin/chromium-browser"

            # 尝试多个可能的chromedriver路径
            chromedriver_paths = [
                "/usr/bin/chromedriver",
                "/usr/local/bin/chromedriver",
                "/snap/bin/chromium.chromedriver",
                "/home/lc/.local/bin/chromedriver",
            ]

            chromedriver_path = None
            for path in chromedriver_paths:
                if os.path.exists(path):
                    chromedriver_path = path
                    break

            if chromedriver_path:
                service = Service(chromedriver_path)
            else:
                # 如果没有找到，尝试下载
                try:
                    service = Service(
                        ChromeDriverManager(chrome_type="chromium").install()
                    )
                except:
                    # 下载失败，尝试使用系统路径
                    service = Service("chromedriver")

            self.driver = webdriver.Chrome(service=service, options=chrome_options)
            self.driver.execute_script(
                "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
            )

            logger.info("Chrome驱动设置完成")
            return True

        except Exception as e:
            logger.error(f"设置Chrome驱动失败: {e}")
            return False

    def add_callback(self, event_type: str, callback: Callable):
        """添加事件回调"""
        if event_type in self.callbacks:
            self.callbacks[event_type].append(callback)
            logger.info(f"添加 {event_type} 事件回调")

    def get_room_info(self) -> Dict:
        """获取房间信息"""
        try:
            if not self.driver:
                if not self._setup_driver():
                    return {"error": "无法初始化浏览器"}

            logger.info(f"正在访问直播间: {self.room_url}")
            self.driver.get(self.room_url)

            # 等待页面加载
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.TAG_NAME, "body"))
            )

            # 尝试获取房间标题
            room_title = "未知直播间"
            title_selectors = [
                "title",
                '[data-e2e="live-title"]',
                ".live-title",
                "h1",
                "h2",
            ]

            for selector in title_selectors:
                try:
                    title_element = self.driver.find_element(By.CSS_SELECTOR, selector)
                    if title_element and title_element.text.strip():
                        room_title = title_element.text.strip()
                        break
                except:
                    continue

            # 获取当前URL（可能会有重定向）
            current_url = self.driver.current_url

            room_info = {
                "room_id": self.room_url.split("/")[-1],
                "title": room_title,
                "url": current_url,
                "status": "connected",
            }

            logger.info(f"房间信息获取成功: {room_info}")
            return room_info

        except Exception as e:
            logger.error(f"获取房间信息失败: {e}")
            return {"error": str(e)}

    def _find_comment_container(self):
        """查找评论容器"""
        for selector in self.comment_selectors:
            try:
                element = self.driver.find_element(By.CSS_SELECTOR, selector)
                if element:
                    logger.info(f"找到评论容器: {selector}")
                    return element
            except:
                continue

        # 如果找不到特定选择器，尝试搜索包含关键词的元素
        try:
            # 搜索包含评论相关类名的元素
            elements = self.driver.find_elements(
                By.XPATH,
                "//*[contains(@class, 'comment') or contains(@class, 'danmu') or contains(@class, 'chat')]",
            )
            if elements:
                logger.info("通过关键词找到可能的评论容器")
                return elements[0]
        except:
            pass

        logger.warning("未找到评论容器")
        return None

    def _extract_comments(self):
        """提取评论数据"""
        try:
            comment_container = self._find_comment_container()
            if not comment_container:
                return []

            # 获取当前页面的HTML
            page_source = self.driver.page_source
            soup = BeautifulSoup(page_source, "html.parser")

            # 调试：保存页面HTML用于分析（仅第一次）
            if not hasattr(self, "_debug_saved"):
                try:
                    with open(
                        "/home/lc/qustions_tools/debug_page.html", "w", encoding="utf-8"
                    ) as f:
                        f.write(page_source)
                    logger.info("页面HTML已保存到 debug_page.html 用于调试")
                    self._debug_saved = True
                except Exception as e:
                    logger.warning(f"保存调试HTML失败: {e}")

            comments = []

            # 使用正确的抖音直播评论选择器
            comment_item_selectors = [
                ".webcast-chatroom___item",  # 抖音直播专用评论项选择器
                '[class*="webcast-chatroom___item"]',
                '[data-e2e="comment-item"]',
                ".comment-item",
                ".danmu-item",
                ".chat-item",
                '[class*="comment-item"]',
                '[class*="danmu-item"]',
            ]

            comment_elements = []
            used_selector = None

            for selector in comment_item_selectors:
                elements = soup.select(selector)
                if elements:
                    comment_elements = elements
                    used_selector = selector
                    logger.info(f"使用选择器 {selector} 找到 {len(elements)} 个元素")
                    break

            if not comment_elements:
                # 如果还是没找到，直接搜索所有包含文本的元素
                comment_elements = soup.find_all(text=True)
                logger.info(f"备用方案：找到 {len(comment_elements)} 个文本节点")
                used_selector = "text_nodes"

            processed_count = 0
            for element in comment_elements:
                try:
                    # 专门针对抖音直播评论结构的提取逻辑
                    if (
                        used_selector == ".webcast-chatroom___item"
                        or used_selector == '[class*="webcast-chatroom___item"]'
                    ):
                        # 抖音直播评论结构
                        username = "未知用户"
                        comment_text = ""

                        # 提取用户名
                        user_selectors = [
                            ".u2QdU6ht",
                            '[class*="u2QdU6ht"]',
                            ".user-name",
                            ".username",
                        ]
                        for user_selector in user_selectors:
                            user_element = element.select_one(user_selector)
                            if user_element:
                                username_text = user_element.get_text(strip=True)
                                if username_text.endswith("："):
                                    username = username_text[:-1]  # 去掉冒号
                                else:
                                    username = username_text
                                break

                        # 提取评论内容
                        content_selectors = [
                            ".webcast-chatroom___content-with-emoji-text",
                            ".WsJsvMP9",
                            '[class*="content"]',
                            '[class*="WsJsvMP9"]',
                        ]
                        for content_selector in content_selectors:
                            content_elements = element.select(content_selector)
                            if content_elements:
                                # 合并所有内容元素的文本
                                comment_parts = []
                                for content_elem in content_elements:
                                    text = content_elem.get_text(strip=True)
                                    if text:
                                        comment_parts.append(text)
                                comment_text = " ".join(comment_parts)
                                break

                        # 如果没有找到内容，尝试获取整个元素的文本
                        if not comment_text:
                            comment_text = element.get_text(strip=True)
                            # 如果包含用户名，尝试去掉用户名部分
                            if username != "未知用户" and comment_text.startswith(
                                username
                            ):
                                comment_text = (
                                    comment_text[len(username) :].lstrip("：").strip()
                                )

                    else:
                        # 其他选择器的通用处理
                        if used_selector == "text_nodes":
                            comment_text = str(element).strip()
                        else:
                            comment_text = element.get_text(strip=True)
                        username = "未知用户"

                    # 过滤掉太短、空的内容或明显的系统消息
                    if not comment_text or len(comment_text) < 2:
                        continue

                    # 过滤掉系统消息和无关内容
                    if any(
                        keyword in comment_text
                        for keyword in [
                            "欢迎来到直播间",
                            "加入了直播间",
                            "来了",
                            "抖音严禁",
                            "script",
                            "style",
                            "function",
                            "var ",
                            "const ",
                            "let ",
                        ]
                    ):
                        continue

                    # 生成唯一标识符
                    comment_id = f"{hash(comment_text)}"

                    # 避免重复处理
                    if comment_id in self.processed_comments:
                        continue

                    # 记录调试信息
                    if processed_count < 5:
                        logger.info(
                            f"发现评论: {username}: '{comment_text}' (长度: {len(comment_text)})"
                        )

                    processed_count += 1

                    comment_data = {
                        "content": comment_text,
                        "user": username,
                        "user_id": "",
                        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        "room_id": self.room_url.split("/")[-1],
                    }

                    comments.append(comment_data)
                    self.processed_comments.add(comment_id)

                    # 记录成功提取的评论
                    logger.info(f"成功提取评论: {username}: {comment_text}")

                    # 触发评论回调
                    for callback in self.callbacks.get("comment", []):
                        try:
                            callback(comment_data)
                        except Exception as e:
                            logger.error(f"评论回调执行失败: {e}")

                except Exception as e:
                    logger.debug(f"处理单条评论失败: {e}")
                    continue

            if processed_count > 0:
                logger.info(
                    f"本次处理了 {processed_count} 个文本元素，提取到 {len(comments)} 条有效评论"
                )

            return comments

        except Exception as e:
            logger.error(f"提取评论失败: {e}")
            return []

    def _monitor_worker(self):
        """监听工作线程"""
        logger.info("开始监听评论")

        try:
            while self.is_running:
                try:
                    # 提取评论
                    comments = self._extract_comments()
                    if comments:
                        logger.info(f"发现 {len(comments)} 条新评论")

                    # 等待一段时间再次检查
                    time.sleep(2)  # 每2秒检查一次

                except Exception as e:
                    logger.error(f"监听过程中出错: {e}")
                    time.sleep(5)  # 出错后等待更长时间

        except Exception as e:
            logger.error(f"监听工作线程异常: {e}")
        finally:
            logger.info("监听工作线程结束")

    def start_monitoring(self):
        """开始监听"""
        if self.is_running:
            logger.warning("监听器已在运行中")
            return

        try:
            # 设置浏览器驱动
            if not self._setup_driver():
                raise Exception("无法初始化浏览器驱动")

            # 访问直播间页面
            logger.info(f"正在访问直播间: {self.room_url}")
            self.driver.get(self.room_url)

            # 等待页面加载
            WebDriverWait(self.driver, 15).until(
                EC.presence_of_element_located((By.TAG_NAME, "body"))
            )

            # 等待更长时间让JavaScript完全加载
            time.sleep(5)

            # 查找评论容器
            comment_container = self._find_comment_container()
            if not comment_container:
                logger.warning("未找到评论容器，但继续尝试监听")

            # 启动监听
            self.is_running = True
            self.monitor_thread = threading.Thread(
                target=self._monitor_worker, daemon=True
            )
            self.monitor_thread.start()

            logger.info("监听已启动")

        except Exception as e:
            logger.error(f"启动监听失败: {e}")
            self.stop_monitoring()
            raise

    def stop_monitoring(self):
        """停止监听"""
        logger.info("正在停止监听...")

        self.is_running = False

        if self.monitor_thread and self.monitor_thread.is_alive():
            self.monitor_thread.join(timeout=5)

        if self.driver:
            try:
                self.driver.quit()
            except:
                pass
            self.driver = None

        logger.info("监听已停止")

    def __del__(self):
        """析构函数"""
        self.stop_monitoring()


class LiveDataProcessor:
    """直播数据处理器（兼容性保持）"""

    def __init__(self):
        pass

    def process_comment(self, comment_data: Dict) -> Dict:
        """处理评论数据"""
        return comment_data

    def process_gift(self, gift_data: Dict) -> Dict:
        """处理礼物数据"""
        return gift_data
